package game;

import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glVertex2i;
import game.camera.Camera;
import game.graphics.effects.GraphicEffectsManager;
import game.graphics.effects.GunshotExplosionEffect;

import java.awt.Rectangle;

import application.Window;

/**
 * Implements a gunshot.
 * It damages enemies and explodes after hit of the object.
 * 
 * @author Tomas Zima
 */
public class Gunshot implements ICollidable
{
	/**
	 * Constructor.
	 * Sets origin coordinates of a shot and its way (left or right).
	 * 
	 * @param x
	 * 	Origin coordinate in the X axis.
	 * 
	 * @param y
	 * 	Origin coordinate in the Y axis.
	 * 
	 * @param way
	 * 	True: right.
	 * 	False: left.
	 */
	public Gunshot(int x, int y, boolean way)
	{
		this.positionX		= x;
		this.positionY		= y;
		this.way			= way;
		this.startPositionX	= x;
	}
	
	/**
	 * Set coordinates of shot.
	 * 
	 * @param x
	 * @param y
	 */
	public void setXY(int x, int y)
	{
		this.positionX = x;
		this.positionY = y;
	}
	
	/**
	 * Returns bounding boxes of shot.
	 */
	@Override
	public Rectangle[] getBoundingBoxes()
	{
		Rectangle result[] = new Rectangle[1];
		
		result[0]			= new Rectangle();
		result[0].x			= (int) positionX;
		result[0].y			= (int) positionY;
		result[0].width		= width;
		result[0].height	= height;
		
		return result;
	}

	/*
	 * These methods are unused. 
	 */
	@Override public void removeCollision() {}
	@Override public void notInCollision() {}
	@Override public void collidesDown() {}
	@Override public void notCollidesDown() {}

	/**
	 * Destroy gunshot.
	 * Call if it collides with an object.
	 */
	@Override 
	public void destroy()
	{
		this.destroyed = true;
	}

	/**
	 * Checks if object can collide with a map.
	 */
	@Override
	public boolean isCollidableWithMap()
	{
		return true;
	}

	/**
	 * Checks if object should be destroyed by a collision.
	 */
	@Override
	public boolean isSensitivelyDestroyable()
	{
		return true;
	}

	/**
	 * Redraw a gunshot.
	 * 
	 * @param cameraX
	 * @param cameraY
	 */
	public void redraw(int cameraX, int cameraY)
	{
		// Get relative coordinates according to current camera position
		int relX = Camera.getPositionX((int) positionX, cameraX);
		int relY = Camera.getPositionY((int) positionY, cameraY);

		// Set some properties for drawing
		Window.disableTexColorMixing();
		Window.disableTexturing();
		
		// Draw
		glColor3f(0.0f, 0.0f, 0.0f);
		glBegin(GL_QUADS);
			glVertex2i((int) relX, (int) relY);
			glVertex2i((int) relX + width, (int) relY);
			glVertex2i((int) relX + width, (int) relY + height);
			glVertex2i((int) relX, (int) relY + height);
		glEnd();
		
		// Set properties back to normal state
		Window.enableTexColorMixing();
		Window.disableTexColorMixing();
	}
	
	/**
	 * Update a gunshot (move).
	 * 
	 * @param deltaTime
	 */
	public void update(long deltaTime)
	{
		// Remove gunshot if it is flying too long
		// (this is protection against shooting over the whole map).
		if (Math.abs(positionX - startPositionX) >= runLimit)
		{
			this.destroyed = true;
		}
		// Move with gunshot
		else
		{
			if (way)
			{
				this.positionX += (deltaTime / 1000.0f) * 500;
			}
			else
			{
				this.positionX -= (deltaTime / 1000.0f) * 500;
			}
		}
	}
	
	/**
	 * Checks if gunshot was destroyed and should be removed from
	 * collision checker and gunshot manager.
	 */
	public boolean isDestroyed()
	{
		if (this.destroyed && !exploded)
		{
			exploded = true;
			GraphicEffectsManager.getInstance().registerNewEffect(new GunshotExplosionEffect((int) positionX, (int) positionY));
		}
		
		return destroyed;
	}

	/**
	 * Checks if object has destroying character
	 * (if it collides with another object, this object will be damaged).
	 */
	@Override
	public boolean hasDestroyingCharacter()
	{
		return true;
	}
	
	/**
	 * Checks if this object can be damaged by other object with
	 * destroying character.
	 */
	@Override
	public boolean isDamagable()
	{
		return false;
	}
	
	/**
	 * THIS METHOD IS UNUSED!
	 */
	@Override
	public void damage(int lives)
	{
		//
	}

	/**
	 * Checks if object is manually controlled by player.
	 */
	@Override
	public boolean isPlayerControlled()
	{
		return false;
	}
	
	/**
	 * Checks if object acts like an enemy.
	 */
	@Override
	public boolean isEnemy()
	{
		return false;
	}
	
	// Current position
	private float positionX;
	private float positionY;
	
	// Physical properties
	private int width = 10;
	private int height = 5;
	
	// Was gunshot already destroyed?
	private boolean destroyed = false;

	// Way of fly
	private boolean way;
	
	// Did gunshot already explode?
	private boolean exploded = false;
	
	// Beginning position at the X axis
	// (to be able to check if it's not flying too long)
	private float	startPositionX;
	
	// Distance which gunshot should fly
	// (if it didn't collide)
	private int		runLimit = 2000;
}
